//
//  MadMultiThreadedDatabaseLoader.m
//  MadGTD
//
//  Created by Fuzhou Chen on 7/29/12.
//  Copyright (c) 2012 Fuzhou Chen. All rights reserved.
//

#import "MadGTDModel.h"
#include "MadDebug.h"
#include <pthread.h>

static void*
LoadDBThreadFunc(void* param)
{
    MadGTDModel* model = (MadGTDModel*)param;
    [model syncLoadDb];
    return NULL;
}

@implementation MadGTDModel

@synthesize dbName;
@synthesize dbPath;
@synthesize isDbLoaded;

-(id)initWithDbInDocuments:(NSString*)docName
{
    MAD_CHK_PARAM_OR_TERMINATE(docName != nil, ("docName == nil"));
    self = [super init];
    if (self)
    {
        _dbName = [[NSString alloc] initWithString:docName];
        NSString *documentsDirectory = [NSHomeDirectory() 
                                        stringByAppendingPathComponent:@"Documents"];
        NSString *filePath = [documentsDirectory 
                              stringByAppendingPathComponent:@"mad.db"];
        _dbPath = [filePath retain];
        _isDbLoaded = false;
        _loaderThread = NULL;
    }
    return self;
}

-(void)dealloc
{
    if (_db)
        MadDbClose(_db);
    if (_dbName)
        [_dbName release];
    if (_loaderThread)
        pthread_join(_loaderThread, NULL);
    [super dealloc];
}

-(void)asyncLoadDb
{
    // Note: In theory, _isDbLoaded should be protected by a lock. However,
    // it's safe ignore it because there's only one controller interacting
    // with model.
    if (_isDbLoaded)
        return;
    pthread_t loaderThread = NULL;
    int result = MAD_SUCCESS;
    result = pthread_create(&loaderThread, NULL, LoadDBThreadFunc, (void*)self);
    if (result != 0)
    {
        // We can't continue if database cannot be loaded.
        NSLog(@"Fatal: Failed to start loading database. code = %d", result);
        exit(EXIT_FAILURE);
    }
    _loaderThread = loaderThread;
    loaderThread = NULL;
Exit:
    if (loaderThread)
        pthread_join(loaderThread, NULL);
    return;
}

-(void)syncLoadDb
{
    if (_isDbLoaded)
        return;
    MadDatabase* db = NULL;
    MadResult result = MadDbOpen([_dbPath UTF8String], &db);
    if (result != MAD_SUCCESS)
    {
        // We can't continue if database cannot be loaded.
        NSLog(@"Fatal: Failed to initialize database. code = %ld", result);
        exit(EXIT_FAILURE);
    }
    _db = db;
    db = NULL;
    _isDbLoaded = true;
    // TODO Shall I load content here?

    // Now notify listeners. They can access database now.
    NSNotificationQueue* queue = [NSNotificationQueue defaultQueue];
    NSNotification* loadComplete = [NSNotification
                                    notificationWithName:MAD_DB_LOADED_NOTIFY
                                    object:nil];
    [queue enqueueNotification:loadComplete postingStyle:NSPostASAP];
Exit:
    MadDbClose(db);
}

@end
